#!/usr/bin/env python3
"""
GUI 版 PDF 签名删除器
支持多选/单选，原地覆盖保存，自动备份（*.bak）
"""
import sys
import shutil
from pathlib import Path
import pikepdf
import tkinter as tk
from tkinter import filedialog, messagebox, scrolledtext

BACKUP_SUFFIX = ".bak"

# -------------------------------------------------
# 业务函数（不含 UI）
# -------------------------------------------------
def strip_signatures(pdf_path: Path) -> None:
    """原地删除签名字段＋常见签名外观＋/Perms，带备份"""
    bak = pdf_path.with_suffix(pdf_path.suffix + BACKUP_SUFFIX)
    shutil.copy2(pdf_path, bak)          # 先备份

    with pikepdf.open(pdf_path, allow_overwriting_input=True) as pdf:
        # 1. 清字段
        if '/AcroForm' in pdf.Root:
            fields = pdf.Root.AcroForm.get('/Fields', [])
            non_sig = [f for f in fields if str(f.get('/FT')) != '/Sig']
            pdf.Root.AcroForm.Fields = non_sig
            if not non_sig:
                del pdf.Root.AcroForm

        # 2. 清页面签名外观
        for page in pdf.pages:
            resources = page.get('/Resources', {})
            xobj = resources.get('/XObject', {})
            if xobj:
                for name in list(xobj.keys()):
                    if str(name).startswith(('/DS', '/Signature')):
                        del xobj[name]

        # 3. 清 /Perms
        if '/Perms' in pdf.Root:
            del pdf.Root.Perms

        pdf.save(pdf_path)

# -------------------------------------------------
# GUI 部分
# -------------------------------------------------
class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("PDF 数字签名删除工具")
        self.geometry("600x400")
        self._create_widgets()

    # ---------- 界面 ----------
    def _create_widgets(self):
        top = tk.Frame(self)
        top.pack(side="top", fill="x", padx=10, pady=10)

        btn_sel = tk.Button(top, text="选择 PDF 文件", command=self.select_pdfs)
        btn_sel.pack(side="left")

        btn_run = tk.Button(top, text="开始删除签名", command=self.run_removal)
        btn_run.pack(side="left", padx=10)

        self.txt = scrolledtext.ScrolledText(self, height=15, state="disabled")
        self.txt.pack(fill="both", expand=True, padx=10, pady=10)

        self.paths = []   # 存放选中的文件

    # ---------- 日志 ----------
    def log(self, msg: str):
        self.txt.configure(state="normal")
        self.txt.insert("end", msg + "\n")
        self.txt.see("end")
        self.txt.configure(state="disabled")

    # ---------- 选择 ----------
    def select_pdfs(self):
        files = filedialog.askopenfilenames(
            title="请选择需要处理的 PDF 文件",
            filetypes=[("PDF files", "*.pdf"), ("All files", "*.*")]
        )
        self.paths = [Path(f) for f in files]
        self.log(f"已选择 {len(self.paths)} 个文件")
        for p in self.paths:
            self.log(f"  - {p}")

    # ---------- 执行 ----------
    def run_removal(self):
        if not self.paths:
            messagebox.showwarning("提示", "请先选择 PDF 文件")
            return
        for p in self.paths:
            try:
                strip_signatures(p)
                self.log(f"[完成] {p}")
            except Exception as e:
                self.log(f"[失败] {p}  ->  {e}")
        messagebox.showinfo("完毕", "处理完成！原文件已备份为 *.bak")

# -------------------------------------------------
# main
# -------------------------------------------------
def main():
    # Windows 高 DPI 自适应
    try:
        from ctypes import windll
        windll.shcore.SetProcessDpiAwareness(1)
    except Exception:
        pass

    App().mainloop()

if __name__ == "__main__":
    main()
